<script>
  import TileMap from '../TileMap.svelte';
  import Log from '../Log.svelte';
  import Inventory from '../Inventory.svelte';
  import CharStatus from '../CharStatus.svelte';
  import Environment from '../Environment.svelte';
  import QuickMenu from '../QuickMenu.svelte';
  import SelectedInfo from '../SelectedInfo.svelte';
  import { createWorld, hasComponent } from 'bitecs';
  import { getTime, getPlayer, describe } from '$lib';
  import { prepareSample } from '$lib/psychic';
  import { renderStack, renderTiles } from '$lib/render';
  import { log, recentLog } from '$lib/log';
  import { randomSeed } from '$lib/random';
  import { getPos2, onTile } from '$lib/pos2';
  import { MoveAction } from '$lib/walk';
  import { onMount } from 'svelte';
  import { PickupAction, getInventory } from '$lib/inventory';
  import { Item } from '$lib/item';
  import { setUpdate, update } from '$lib/ui';
  import { Creature, Impassable } from '$lib/components';
  import { AttackAction } from '$lib/attack';
  import { Door, OpenAction } from '$lib/door';
  import { simulateWorld } from '$lib/simulate';
  import { WaitAction } from '$lib/wait';

  let screen = $state({
    tiles: [],
    environment: {
      features: [],
      creatures: [],
      items: [],
    },
    log: [],
    inventory: [],
    inventoryStatus: 'idle',
  });

  let zoomlevel = $state(25);

  const world = createWorld();

  let selected = $state(undefined);

  let rootElement;

  const select = (entity) => {
    if (selected === entity) {
      selected = undefined;
    } else {
      selected = entity;
    }
  };

  onMount(() => {
    randomSeed(123);
    prepareSample(world);
    update();
  });

  const movementKeys = {
    j: [0, 1],
    k: [0, -1],
    h: [-1, 0],
    l: [1, 0],
    y: [-1, -1],
    u: [1, -1],
    b: [-1, 1],
    n: [1, 1],
  };

  setUpdate(() => {
    const r = Math.floor((1050 / zoomlevel - 1) / 2);
    [screen.tiles, screen.environment] = renderTiles(renderStack, world, r);
    screen.log = recentLog();
    screen.inventory = getInventory(world);
  });

  // TODO: implement UI
  const fullscreen = () => {
    rootElement.requestFullscreen();
  };

  const onKeyDown = (ev) => {
    console.log(ev);
    const movement = movementKeys[ev.key];
    const pc = getPlayer(world);
    let cmd;
    if (movement) {
      const [dx, dy] = movement;
      const {x, y} = getPos2(pc);
      const x1 = x + dx;
      const y1 = y + dy;
      // TODO: check tile type
      const things = onTile(world, x1, y1);
      const creature = things.find((e) => hasComponent(world, Creature, e));
      const obstacle = things.find((e) => hasComponent(world, Impassable, e));
      if (creature !== undefined) {
        cmd = AttackAction(creature);
      } else if (obstacle !== undefined) {
        if (hasComponent(world, Door, obstacle)) {
          cmd = OpenAction(obstacle);
        } else {
          log(`You can't walk through ${describe(world, obstacle)} (yet?)`);
        }
      } else {
        cmd = MoveAction(dx, dy, 10);
      }
    } else if (ev.key === '.') {
      cmd = WaitAction(5);
    } else if (ev.key === 'g') {
      const {x, y} = getCoord(pc);
      const items = onTile(world, x, y).filter(e => hasComponent(world, Item, e));;
      if (items.length > 1) {
        log('Multi-pickup NOT IMPLEMENTED');
      } else if (items.length === 1) {
        cmd = PickupAction(items[0]);
      } else {
        log('Nothing to pickup here!');
      }
    } else if (ev.key === 'i') {
      screen.inventoryStatus = 'active';
    } else if (ev.key === 'd') {
      log('TODO DROP');
      screen.inventoryStatus = 'drop';
    } else if (ev.key === 'z') {
      ++zoomlevel;
    } else if (ev.key === 'Z') {
      zoomlevel = Math.max(zoomlevel-1, 1);
    } else if (ev.key === '@') {
      selected = pc;
    } else {
      log(`Key unbound: ${ev.key}`);
    }
    if (cmd) {
      simulateWorld(world, cmd);
    }
    update();
  };
</script>

<div class="main-grid" bind:this={rootElement}>
  <div class="leftside">
    <Environment {world} {select} {selected} environment={screen.environment} />
    <Inventory {world} {select} {selected} inventory={screen.inventory} status={screen.inventoryStatus} />
    <SelectedInfo {world} {selected} />
  </div>
  <TileMap bind:tiles={screen.tiles} {select} {selected} {zoomlevel} />
  <div class="rightside">
    <CharStatus />
    <Log bind:log={screen.log} />
  </div>
  <QuickMenu {world} />
</div>

<svelte:window on:keydown={onKeyDown} />

<style>
  .main-grid {
    display: grid;
    grid-template-columns: 1fr 1050px 1fr;
    grid-template-rows: 1050px 30px;
    grid-template-areas:
      "leftside main rightside"
      "quickmenu quickmenu quickmenu";
  }

  .leftside {
    grid-area: leftside;
  }

  .rightside {
    grid-area: rightside;
  }

  .screen {
    grid-area: main;
  }
</style>
